package cn.i7baozh.boot.learn.thirdproperty;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.BootstrapRegistry;
import org.springframework.boot.ConfigurableBootstrapContext;
import org.springframework.boot.context.config.ConfigDataLocation;
import org.springframework.boot.context.config.ConfigDataLocationNotFoundException;
import org.springframework.boot.context.config.ConfigDataLocationResolver;
import org.springframework.boot.context.config.ConfigDataLocationResolverContext;
import org.springframework.boot.context.config.ConfigDataResourceNotFoundException;
import org.springframework.boot.context.config.Profiles;
import org.springframework.boot.context.properties.bind.BindResult;
import org.springframework.boot.context.properties.bind.Binder;

import java.util.List;

/**
 * 通过本地类取初始化你自己的配置和服务
 *
 * 一定要先看package下的package-info.java
 *
 * nacos 实现类 NacosConfigDataLocationResolver
 *
 * @author zhangbaoqi532
 * @date 2025/2/24
 */
@Slf4j
public class MyConfigDataLocationResolver implements ConfigDataLocationResolver<MyPropertyDataResource> {

    private String prefix = "thirdXXX:";
    /**
     * 这个方法判断是不是要处理
     */
    @Override
    public boolean isResolvable(ConfigDataLocationResolverContext context, ConfigDataLocation location) {

        log.info("isResolvable {}", location);
        //判断 location是不是以自定义prefix开始的 是的话才处理
        if (!location.hasPrefix(prefix)) {
            return false;
        }
        //可以在加上本地配置中有没有开关之类的
        BindResult<Boolean> open = context.getBinder().bind("third.enabled", Boolean.class);
        if (!open.isBound()) {
            //值不存在
            return false;
        }
        return open.get();
    }

    //这个是具体处理了，不过这个方法没有激活环境，所以一般返回空集合，nacos就是返回空集合
    @Override
    public List<MyPropertyDataResource> resolve(ConfigDataLocationResolverContext context,
                                                ConfigDataLocation location) throws ConfigDataLocationNotFoundException, ConfigDataResourceNotFoundException {
        return List.of();
    }

    /**
     * 像nacos就是实现了这个
     * 主要干2个事
     * 一个是通过location拿到你配置的值、profiles(spring.profiles.active)拿到激活环境这些来初始化你的配置dto
     * spring:
     *   config:
     *     import:
     *       - optional:thirdXXX:aaabbb
     *       - optional:thirdXXX:cccddd
     *  例如上面的配置就分别拿到 aaabbb 和 cccddd
     * 还有一个是把你的服务注册到spring容器里，不能用@Bean的方式，因为此时还没生效
     */
    @Override
    public List<MyPropertyDataResource> resolveProfileSpecific(ConfigDataLocationResolverContext context,
                                                               ConfigDataLocation location, Profiles profiles)
            throws ConfigDataLocationNotFoundException {

        //把我的服务注册到容器里
        ConfigurableBootstrapContext bootstrapContext = context.getBootstrapContext();
        if (!bootstrapContext.isRegistered(MyConfigDataService.class)) {
            MyConfigDataService myConfigDataService = new MyConfigDataService();
            Binder binder = context.getBinder();
            BindResult<String> url = binder.bind("third.xx.url", String.class);
            if (url.isBound()) {
                myConfigDataService.setUrl(url.get());
            }
            BindResult<String> username = binder.bind("third.xx.username", String.class);
            if (username.isBound()) {
                myConfigDataService.setUsername(username.get());
            }
            //初始化
            myConfigDataService.init();
            bootstrapContext.register(MyConfigDataService.class, BootstrapRegistry.InstanceSupplier.of(myConfigDataService));
        }
        //我的配置dto初始化
        return List.of(new MyPropertyDataResource(location.getNonPrefixedValue(prefix), profiles));
    }
}
